/**
 * 将十六进制颜色转换为RGB对象
 * @param {string} hex - 十六进制颜色字符串，格式为"#RRGGBB"或"RRGGBB"
 * @returns {Object|null} - 返回一个包含RGB分量的对象，如果输入格式错误则返回null
 */
export const hexToRgb = (hex) => {
  if (!hex) return null;
  // 去除空格并统一格式
  const cleanHex = hex.trim().toLowerCase();
  // 使用正则表达式匹配十六进制颜色字符串
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(cleanHex);

  if (result) {
    return {
      r: parseInt(result[1], 16),
      g: parseInt(result[2], 16),
      b: parseInt(result[3], 16),
    };
  }
  return null;
};

/**
 * 将RGB数值限制在0-255范围内
 * @param {number} value - 需要限制的数值
 * @returns {number} - 限制后的数值
 */
const clamp = (value) => Math.max(0, Math.min(255, Math.round(value)));

/**
 * 根据给定的因素将一种颜色平滑过渡到另一种颜色
 * @param {string} color1 起始颜色的十六进制表示
 * @param {string} color2 结束颜色的十六进制表示
 * @param {number} factor 过渡因素，范围在0到1之间
 * @returns {string|null} 过渡后的颜色的十六进制表示，输入无效时返回null
 */
export const interpolateColor = (color1, color2, factor = 0) => {
  // 输入验证
  if (!color1 || !color2) return null;

  // 确保factor在0-1范围内
  const safeFactor = Math.max(0, Math.min(1, factor));

  // 转换颜色
  const rgb1 = hexToRgb(color1);
  const rgb2 = hexToRgb(color2);

  if (!rgb1 || !rgb2) return null;

  // RGB到十六进制的转换函数
  const rgbToHex = (r, g, b) =>
    "#" +
    [r, g, b]
      .map((x) => {
        const hex = clamp(x).toString(16);
        return hex.length === 1 ? "0" + hex : hex;
      })
      .join("");

  // 计算过渡后的颜色值，使用clamp确保在有效范围内
  const r = clamp(rgb1.r + safeFactor * (rgb2.r - rgb1.r));
  const g = clamp(rgb1.g + safeFactor * (rgb2.g - rgb1.g));
  const b = clamp(rgb1.b + safeFactor * (rgb2.b - rgb1.b));

  return rgbToHex(r, g, b);
};

/**
 * 根据给定的数值和颜色范围区间，计算出一个中间颜色
 * @param {Array} colorRanges - 颜色范围对象数组
 * @param {number} num - 用于插值计算的数值
 * @returns {string|null} - 插值计算得出的颜色值，输入无效时返回null
 */
export const interpolatedColor = (colorRanges, num) => {
  // 输入验证
  if (
    !Array.isArray(colorRanges) ||
    colorRanges.length < 1 ||
    num === undefined
  ) {
    return null;
  }

  // 验证每个范围对象的格式
  const validRanges = colorRanges.every(
    (range) =>
      range &&
      typeof range.range === "number" &&
      typeof range.color === "string",
  );
  if (!validRanges) return null;

  // 对颜色范围数组进行降序排序
  const sortedRanges = [...colorRanges].sort((a, b) => b.range - a.range);

  // 边界情况处理
  if (num >= sortedRanges[0].range) return sortedRanges[0].color;
  if (num <= sortedRanges[sortedRanges.length - 1].range) {
    return sortedRanges[sortedRanges.length - 1].color;
  }

  // 找到合适的范围区间
  const lowerRange = sortedRanges.find((range) => range.range <= num);
  const upperRange = sortedRanges.find((range) => range.range > num);

  if (!lowerRange || !upperRange) return null;

  // 计算插值因子
  const rangeDiff = upperRange.range - lowerRange.range;
  // 避免除以零
  if (rangeDiff === 0) return lowerRange.color;

  const valueDiff = num - lowerRange.range;
  const factor = valueDiff / rangeDiff;

  return interpolateColor(lowerRange.color, upperRange.color, factor);
};
